from threading import Thread, Event
from time import sleep
import socket

__author__ = 'cain76'


class MyServer:
    _Host = ''
    _Port = 7777
    _thread = None
    server = None
    recv = None
    connect = None
    disconnect = None

    def __init__(self):
        self._loop = Event()

    def start(self, host, port):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.settimeout(0.0)
        self._Host = host
        self._Port = port
        try:
            self.server.bind((self._Host, self._Port))
        except socket.error:
            print('SERVER: Bind failed')
            return False
        self.server.listen(1)
        self._thread = Thread(target=self.run)
        self._thread.daemon = True
        self._thread.start()

        return True

    def stop(self):
        self._loop.set()

    def set_recv(self, func):
        self.recv = func

    def set_disconnect(self, func):
        self.disconnect = func

    def set_connect(self, func):
        self.connect = func

    def client_loop(self, sock):
        sock.settimeout(0.0)
        while not self._loop.isSet():
            # RECEIVE DATA
            try:
                data = sock.recv(1024)
                if len(data) < 1: break
                self.recv(sock, data.decode('utf-8'))
            except BlockingIOError:
                sleep(0.01)
        print('SERVER: Disconnect ', sock.getpeername())
        sock.close()

    def run(self):
        print('SERVER: Start~~')
        while not self._loop.isSet():
            # Accept the connection once (for starter)
            try:
                (conn, addr) = self.server.accept()
                print('SERVER: Connected (' + addr[0] + ':' + str(addr[1]) + ')')

                t = Thread(target=self.client_loop, args=(conn,))
                t.start()
                if self.connect is not None: self.connect(conn)
            except BlockingIOError:
                sleep(0.01)

        print('SERVER: Stop!!')
        self.server.close()  # When we are out of the loop, we're done, close

